using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Base;
using UtilZ.Dotnet.Ex.Exceptions;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Tcp
{
    /// <summary>
    /// tcp客户端
    /// </summary>
    public class NetTcpClient : ClientAbs
    {
        private readonly NetTcpClientInitPara _tcpClientInitPara;
        /// <summary>
        /// 获取tcp初始化参数
        /// </summary>
        public NetTcpClientInitPara TcpClientInitPara
        {
            get { return this._tcpClientInitPara; }
        }


        private readonly string _name;
        /// <summary>
        /// 
        /// </summary>
        private readonly string _remoteIpStr;

        private NetLinkInfo _linkInfo = null;
        /// <summary>
        /// 获取连接终节点信息
        /// </summary>
        public NetLinkInfo LinkInfo
        {
            get { return _linkInfo; }
        }



        /// <summary>
        /// 连接状态改变通知事件
        /// </summary>
        public event EventHandler<NetConnectedChangedArgs> ConnectChanged;

        private readonly object _connectionCloseNotifyLock = new object();
        /// <summary>
        /// 连接关闭通知
        /// </summary>
        private void ConnectionCloseNotify()
        {
            lock (this._connectionCloseNotifyLock)
            {
                //输出连接断开通知
                var handler = this.ConnectChanged;
                if (handler != null)
                {
                    DisconnectMode disconnectMode;
                    if (this._manualDisconnectFlag)
                    {
                        disconnectMode = DisconnectMode.Active;
                    }
                    else
                    {
                        disconnectMode = DisconnectMode.Passive;
                    }
                    var args = new NetConnectedChangedArgs(ConnectionStatus.Closed, disconnectMode, this._linkInfo?.LocalEndPoint, this._linkInfo?.RemoteEndPoint);
                    handler(this, args);
                }

                //如果是主动连接,则启动重新机制
                if (this._tcpClientInitPara.ConnectType == ConnectTypes.Active)
                {
                    //如果是主动连接，则开始重新连接
                    if (this._manualDisconnectFlag || this._disposed)
                    {
                        return;
                    }
                    else
                    {
                        this.PrimitiveConnectAsync();
                    }
                }
            }
        }

        /// <summary>
        /// 连接打开通知
        /// </summary>
        protected void ConnectionOpenNotify()
        {
            var handler = this.ConnectChanged;
            if (handler != null)
            {
                EndPoint remoteEndPoint = this._tcpClientInitPara.RemoteEndPoint;
                EndPoint localEndPoint = null;
                ConnectionStatus status;
                try
                {
                    Socket client = this._client;
                    if (client != null)
                    {
                        localEndPoint = client.LocalEndPoint;
                        if (client.Connected)
                        {
                            status = ConnectionStatus.Opened;
                        }
                        else
                        {
                            status = ConnectionStatus.Closed;
                        }
                    }
                    else
                    {
                        status = ConnectionStatus.Closed;
                    }
                }
                catch (ObjectDisposedException)
                {
                    status = ConnectionStatus.Closed;
                }
                catch (Exception ex)
                {
                    ZLoger.Error(ex);
                    status = ConnectionStatus.Closed;
                }

                var args = new NetConnectedChangedArgs(status, DisconnectMode.Active, localEndPoint, remoteEndPoint);
                handler(this, args);
            }
        }


        private readonly object _socketDisposeLock = new object();
        private void SocketDispose()
        {
            lock (this._socketDisposeLock)
            {
                if (this._client == null)
                {
                    return;
                }

                this._client.Dispose();
                this._client = null;

                //如果是监听到的连接,且有连接数量限制,则告知tcp监听器连接已断开一个
                AcceptSocketArgs socketArgs = this._tcpClientInitPara.SocketArgs;
                if (socketArgs != null && socketArgs.LimitConnection)
                {
                    socketArgs.Listener.IncrementConnections();
                }
            }
        }





        private readonly object _sendDataLock = new object();
        private Socket _client = null;
        /// <summary>
        /// Socket
        /// </summary>
        public Socket Socket
        {
            get
            {
                return _client;
            }
        }

        /// <summary>
        /// 获取socket连接状态
        /// </summary>
        public override bool Connected
        {
            get
            {
                var client = this._client;
                if (client == null)
                {
                    return false;
                }
                else
                {
                    return client.Connected;
                }
            }
        }

        private bool _asyncConnecting = false;
        private readonly object _connectLock = new object();


        private readonly ThreadEx _syncRecceiveDataThread = null;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();
        private int _continuousReceiveEmptyDataCount = 0;

        /// <summary>
        /// 手动断开连接标识,当调用Disconnect()方法该标识设置为true,其它连接时为false
        /// </summary>
        private bool _manualDisconnectFlag = false;


        private byte[] _buffer = null;
        private BinaryReader _reader = null;
        private readonly NetTcpUnpackerPara _unpackerPara = null;

        private readonly bool _enableSendHeartData = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="initPara">Tcp客户端初始化参数</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public NetTcpClient(NetTcpClientInitPara initPara)
            : base(initPara)
        {
            this._tcpClientInitPara = initPara;
            this._name = initPara.Name;
            this._remoteIpStr = NetHelper.GetIPString(initPara.RemoteEndPoint);

            if (initPara.ReceiveData)
            {
                if (initPara.Unpacker == null)
                {
                    throw new ArgumentException("分包器未指定");
                }

                this._unpackerPara = new NetTcpUnpackerPara()
                {
                    Client = this,
                    Reader = this._reader
                };

                //扩展接收缓存
                this.ExtendReceiveBuffer(initPara.Certificate, initPara.BufferSize);

                if (initPara.ReceiveDataMode == ThreadMode.Sync)
                {
                    string receiveThreadName = initPara.ReceiveThreadName;
                    if (string.IsNullOrWhiteSpace(receiveThreadName))
                    {
                        receiveThreadName = $"tcp接收数据线程{NetHelper.GetIPPortString(initPara.LocalEndPoint)}";
                    }
                    this._syncRecceiveDataThread = new ThreadEx(this.SyncRecceiveDataThreadMethod, receiveThreadName, true);
                }
            }

            if (initPara.ConnectType == ConnectTypes.Passive)
            {
                this.SetTcpClient(initPara.Client);
            }

            if (initPara.ClientHeart != null)
            {
                ClientHeartManager.Instance.Add(this, initPara.ClientHeart);
                this._enableSendHeartData = true;
            }
        }




        private void ExtendReceiveBuffer(X509Certificate certificate, int bufferLength)
        {
            if (this._reader != null)
            {
                this._reader.Dispose();
                this._reader = null;
            }

            var buffer = new byte[bufferLength];
            if (this._buffer != null)
            {
                Array.Copy(this._buffer, 0, buffer, 0, this._buffer.Length);
            }
            this._buffer = buffer;

            if (certificate == null)
            {
                this._reader = new BinaryReader(new MemoryStream(buffer));
            }
            else
            {
                //todo 理论代码先写好,ssl不好找机会验证
                var sslStream = new SslStream(new MemoryStream(buffer));
                sslStream.AuthenticateAsServer(certificate, false, SslProtocols.None, true);
                sslStream.ReadTimeout = 10000;
                sslStream.WriteTimeout = 10000;
                this._reader = new BinaryReader(sslStream);
            }
            this._unpackerPara.Buffer = buffer;
            this._unpackerPara.Reader = this._reader;
        }

#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        private int CaculateExtendParseBufferLength(int oldBufferLength)
        {
            //扩展接收buffer长度
            int newBufferLength = oldBufferLength + (int)(oldBufferLength * this._tcpClientInitPara.BufferSizeFactory);
            if (this._tcpClientInitPara.BufferSizeLimit > 0 && newBufferLength > this._tcpClientInitPara.BufferSizeLimit)
            {
                newBufferLength = this._tcpClientInitPara.BufferSizeLimit;
            }

            if (newBufferLength <= oldBufferLength)
            {
                throw new ArgumentException($"tcp接收缓存数据长度动态调整门限值\"{this._tcpClientInitPara.BufferSizeLimit}\"太小,小于了tcp接收数据最大数据包.");
            }

            ZLoger.Info($"tcp接收缓存数据长度从{oldBufferLength}动态调整为{newBufferLength}");
            return newBufferLength;
        }



        /// <summary>
        /// 同步连接到tcp服务端
        /// </summary>
        public void Connect()
        {
            if (this._tcpClientInitPara.ConnectType != ConnectTypes.Active)
            {
                if (string.IsNullOrEmpty(this._name))
                {
                    throw new InvalidOperationException($"当前连接对象非主动连接类型,不允许连接到服务端.");
                }
                else
                {
                    throw new InvalidOperationException($"当前连接对象非主动连接类型,不允许连接到服务端\"{NetHelper.GetIPPortString(this._tcpClientInitPara.RemoteEndPoint)}({this._name})\".");
                }
            }

            lock (this._connectLock)
            {
                this._manualDisconnectFlag = false;
                var client = this.CreateSocket();
                var remoteEndPoint = this._tcpClientInitPara.RemoteEndPoint;
                try
                {
                    client.Connect(remoteEndPoint);
                    this.SetTcpClient(client);
                }
                catch (SocketException sex)
                {
                    client.Dispose();
#if CORE
                    throw new SocketException(sex.ErrorCode, $"{sex.Message},{NetHelper.GetIPPortString(remoteEndPoint)}");
#else
                    throw new Exception($"{sex.Message},{NetHelper.GetIPPortString(remoteEndPoint)}", sex);
#endif
                }
                catch (Exception ex)
                {
                    client.Dispose();
                    throw new Exception($"{ex.Message},{NetHelper.GetIPPortString(remoteEndPoint)}", ex);
                }
            }
        }

        private Socket CreateSocket()
        {
            Socket client;
            switch (this._tcpClientInitPara.InterNetwork)
            {
                case InterNetworkType.InterNetworkV4:
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    break;
                case InterNetworkType.InterNetworkV6:
                    client = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
                    break;
                case InterNetworkType.All:
                default:
#if NET4_0
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
#else
                    client = new Socket(SocketType.Stream, ProtocolType.Tcp);
#endif
                    break;
            }

            var localEndPoint = this._tcpClientInitPara.LocalEndPoint;
            try
            {
                if (localEndPoint != null)
                {
                    client.Bind(localEndPoint);
                }
            }
            catch (SocketException sex)
            {
                client.Dispose();
#if CORE
                throw new SocketException(sex.ErrorCode, $"{sex.Message},{NetHelper.GetIPPortString(localEndPoint)}");
#else
                throw new Exception($"{sex.Message},{NetHelper.GetIPPortString(localEndPoint)}", sex);
#endif
            }
            catch (Exception ex)
            {
                client.Dispose();
                throw new Exception($"{ex.Message},{NetHelper.GetIPPortString(localEndPoint)}", ex);
            }

            return client;
        }

        /// <summary>
        /// 异步连接到tcp服务端
        /// </summary>
        public void ConnectAsync()
        {
            if (this._tcpClientInitPara.ConnectType != ConnectTypes.Active)
            {
                if (string.IsNullOrWhiteSpace(this._name))
                {
                    ZLoger.Warn($"当前连接对象非主动连接类型,不允许连接到服务端\"{NetHelper.GetIPPortString(this._tcpClientInitPara.RemoteEndPoint)}\".");
                }
                else
                {
                    ZLoger.Warn($"当前连接对象非主动连接类型,不允许连接到服务端\"{NetHelper.GetIPPortString(this._tcpClientInitPara.RemoteEndPoint)}({this._name})\".");
                }
            }

            this.PrimitiveConnectAsync();
        }

        /* .net framwork 不支持这种写法,为了减少代码量,和.NET CORE用一种写法
        /// <summary>
        /// 开启tcp客户端，连接tcp服务器
        /// </summary>
        private async Task PrimitiveConnectAsync()
        {
            //连接tcp服务器
            var initPara = this._tcpClientInitPara;
            int reconnectIntervalMilliseconds = initPara.ReconnectIntervalMilliseconds;
            var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                await client.ConnectAsync(initPara.RemoteEndPoint, CancellationToken.None);
                this.SetTcpClient(client);
                return;
            }
            catch (SocketException sex) when (NetHelper.SocketErrorIsConnectFail(sex.SocketErrorCode))
            {
                //由于目标计算机积极拒绝，无法连接
                if (reconnectIntervalMilliseconds > 0)
                {
                    ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    Thread.Sleep(reconnectIntervalMilliseconds);
                }
                else
                {
                    ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,立即重试...");
                }
            }
            catch (Exception exi)
            {
                if (reconnectIntervalMilliseconds > 0)
                {
                    ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    Thread.Sleep(reconnectIntervalMilliseconds);
                }
                else
                {
                    ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,立即重试...");
                }
            }

            client.Dispose();
            await this.PrimitiveConnectAsync();
        }
        */

        /// <summary>
        /// 开启tcp客户端，连接tcp服务器
        /// </summary>
        private void PrimitiveConnectAsync()
        {
            //连接tcp服务器
            var initPara = this._tcpClientInitPara;
            int reconnectIntervalMilliseconds = initPara.ReconnectIntervalMilliseconds;
            try
            {
                lock (this._connectLock)
                {
                    if (this._asyncConnecting)
                    {
                        return;
                    }
                    this._asyncConnecting = true;

                    this._manualDisconnectFlag = false;
                    var client = this.CreateSocket();

                    //连接tcp服务器
                    var connectEventArg = new SocketAsyncEventArgs();
                    connectEventArg.Completed += this.ConnectEventArg_Completed;
                    connectEventArg.RemoteEndPoint = initPara.RemoteEndPoint;//设置要连接的tcp服务器地址
                    connectEventArg.AcceptSocket = client;
                    bool willRaiseEvent = client.ConnectAsync(connectEventArg);
                    if (!willRaiseEvent)
                    {
                        lock (this._connectLock)
                        {
                            this._asyncConnecting = false;
                            this.SetTcpClient(client);
                        }
                    }
                }
            }
            catch (SocketException sex) when (NetHelper.SocketErrorIsConnectFail(sex.SocketErrorCode))
            {
                //由于目标计算机积极拒绝，无法连接
                if (reconnectIntervalMilliseconds > 0)
                {
                    if (string.IsNullOrWhiteSpace(this._name))
                    {
                        ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    }
                    else
                    {
                        ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    }
                    Thread.Sleep(reconnectIntervalMilliseconds);
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(this._name))
                    {
                        ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,立即重试...");
                    }
                    else
                    {
                        ZLoger.Warn(sex, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,立即重试...");
                    }
                }
            }
            catch (Exception exi)
            {
                if (reconnectIntervalMilliseconds > 0)
                {
                    if (string.IsNullOrWhiteSpace(this._name))
                    {
                        ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    }
                    else
                    {
                        ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,等待{reconnectIntervalMilliseconds}毫秒后重试...");
                    }
                    Thread.Sleep(reconnectIntervalMilliseconds);
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(this._name))
                    {
                        ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,立即重试...");
                    }
                    else
                    {
                        ZLoger.Warn(exi, $"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,立即重试...");
                    }
                }
            }
        }

        private void ConnectEventArg_Completed(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                e.Completed -= this.ConnectEventArg_Completed;
                this._asyncConnecting = false;

                if (e.LastOperation == SocketAsyncOperation.Connect && e.SocketError == SocketError.Success)
                {
                    lock (this._connectLock)
                    {
                        this._asyncConnecting = false;
                        this.SetTcpClient(e.ConnectSocket);
                    }
                }
                else
                {
                    e.AcceptSocket.Dispose();
                    var initPara = this._tcpClientInitPara;
                    int reconnectIntervalMilliseconds = initPara.ReconnectIntervalMilliseconds;
                    //由于目标计算机积极拒绝，无法连接
                    if (reconnectIntervalMilliseconds > 0)
                    {
                        if (string.IsNullOrEmpty(this._name))
                        {
                            ZLoger.Warn($"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,Socket错误\"{e.SocketError.ToString()}\",等待{reconnectIntervalMilliseconds}毫秒后重试...");
                        }
                        else
                        {
                            ZLoger.Warn($"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,Socket错误\"{e.SocketError.ToString()}\",等待{reconnectIntervalMilliseconds}毫秒后重试...");
                        }

                        Thread.Sleep(reconnectIntervalMilliseconds);
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(this._name))
                        {
                            ZLoger.Warn($"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}\"失败,Socket错误\"{e.SocketError.ToString()}\",立即重试...");
                        }
                        else
                        {
                            ZLoger.Warn($"连接到服务端\"{NetHelper.GetIPPortString(initPara.RemoteEndPoint)}({this._name})\"失败,Socket错误\"{e.SocketError.ToString()}\",立即重试...");
                        }
                    }

                    if (this._disposed)
                    {
                        return;
                    }
                    else
                    {
                        e.Dispose();
                        this.PrimitiveConnectAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                e.Dispose();
                ZLoger.Error(ex);
            }
        }

        private void SetTcpClient(Socket client)
        {
            if (this._tcpClientInitPara.KeepAlive)
            {
#if CORE
                client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, this._tcpClientInitPara.KeepAliveTimeSeconds);
                client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, this._tcpClientInitPara.KeepAliveIntervalSeconds);
                if (this._tcpClientInitPara.ConnectType == ConnectTypes.Active)
                {
                    client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, this._tcpClientInitPara.KeepRetryCount);
                }
#else
                int size = System.Runtime.InteropServices.Marshal.SizeOf((uint)0);
                byte[] keepaliveOptionsValues = new byte[size * 3];
                int offset = 0;

                uint keepAliveEnable = 1;
                uint keepAliveTimeMilliseconds = (uint)this._tcpClientInitPara.KeepAliveTimeSeconds * 1000;
                uint keepAliveIntervalMilliseconds = (uint)this._tcpClientInitPara.KeepAliveIntervalSeconds * 1000;

                BitConverter.GetBytes(keepAliveEnable).CopyTo(keepaliveOptionsValues, offset);
                offset += size;

                BitConverter.GetBytes(keepAliveTimeMilliseconds).CopyTo(keepaliveOptionsValues, offset);
                offset += size;

                BitConverter.GetBytes(keepAliveIntervalMilliseconds).CopyTo(keepaliveOptionsValues, offset);

                client.IOControl(IOControlCode.KeepAliveValues, keepaliveOptionsValues, null);
                client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
#endif
            }

            this._linkInfo = new NetLinkInfo(client.RemoteEndPoint, client.LocalEndPoint);
            if (this._unpackerPara != null)
            {
                this._unpackerPara.LinkInfo = this._linkInfo;
            }

            if (this._tcpClientInitPara.ReceiveBufferSize > 0)
            {
                client.ReceiveBufferSize = this._tcpClientInitPara.ReceiveBufferSize;
            }

            if (this._tcpClientInitPara.SendBufferSize > 0)
            {
                client.SendBufferSize = this._tcpClientInitPara.SendBufferSize;
            }

            if (this._tcpClientInitPara.SendMillisecondsTimeout > 0)
            {
                client.SendTimeout = this._tcpClientInitPara.SendMillisecondsTimeout;
            }

            if (this._tcpClientInitPara.ReceiveMillisecondsTimeout > 0)
            {
                client.ReceiveTimeout = this._tcpClientInitPara.ReceiveMillisecondsTimeout;
            }

            this._client = client;

            if (this._tcpClientInitPara.ReceiveData)
            {
                switch (this._tcpClientInitPara.ReceiveDataMode)
                {
                    case ThreadMode.Async:
                        //异步接收数据
                        var recvEventArgs = new SocketAsyncEventArgs();
                        recvEventArgs.AcceptSocket = client;
                        recvEventArgs.SetBuffer(this._buffer, 0, this._buffer.Length);
                        recvEventArgs.Completed += this.RecvEventArgs_Completed;
                        this._asyncReadOffset = 0;
                        this.StartRecv(recvEventArgs);
                        break;
                    case ThreadMode.Sync:
                    case ThreadMode.Spin:
                        //同步接收数据
                        this._syncRecceiveDataThread.Start(client);
                        break;
                    default:
                        //不接收数据
                        break;
                }
            }

            this.ConnectionOpenNotify();
        }


        private bool SetReaderPosition(BinaryReader reader, long pos)
        {
            try
            {
                if (reader == null)
                {
                    return false;
                }

                Stream stream = reader.BaseStream;
                if (stream == null)
                {
                    return false;
                }

                stream.Position = pos;
                return true;
            }
            catch (ObjectDisposedException)
            {
                return false;
            }
            catch (Exception ex)
            {
                ZLoger.Warn(ex);
                return false;
            }
        }

        private void SyncRecceiveDataThreadMethod(ThreadPara threadPata)
        {
            Socket client = (Socket)threadPata.Para;
            try
            {
                NetTcpUnpackerPara unpackerPara = this._unpackerPara;
                int revLen = 0, writeOffset = 0, readOffset = 0;
                int totalDataLength = 0, unpackedDataLength;
                byte[] buffer = this._buffer;
                int receiveErrorCount = 0;
                int receiveDataMinSize = this._tcpClientInitPara.ReceiveDataSize;
                int receiveDataSize = buffer.Length;
                bool isSpin = this._tcpClientInitPara.ReceiveDataMode == ThreadMode.Spin;

                while (!this._disposed && !threadPata.Token.IsCancellationRequested)
                {
                    try
                    {
                        try
                        {
                            if (isSpin)
                            {
                                while (!threadPata.Token.IsCancellationRequested)
                                {
                                    if (client.Available > 0)
                                    {
                                        revLen = client.Receive(buffer, writeOffset, receiveDataSize, SocketFlags.None);
                                        break;
                                    }
                                }

                                if (threadPata.Token.IsCancellationRequested)
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                revLen = client.Receive(buffer, writeOffset, receiveDataSize, SocketFlags.None);
                            }
                            receiveErrorCount = 0;
                        }
                        catch (ObjectDisposedException)
                        {
                            break;
                        }
                        catch (SocketException sex)
                        {
                            if (sex.SocketErrorCode == SocketError.TimedOut)
                            {
                                //设置了接收数据超时时长,接收数据超时,继续接收
                                continue;
                            }

                            if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                            {
                                if (sex.SocketErrorCode != SocketError.Interrupted &&
                                    sex.SocketErrorCode != SocketError.ConnectionReset &&
                                    sex.SocketErrorCode != SocketError.ConnectionAborted)
                                {
                                    ZLoger.Warn(sex, $"同步接收数据失败,错误码:\"{sex.SocketErrorCode.ToString()}\",RemoteEndPoint:{NetHelper.GetIPPortString(this._linkInfo.RemoteEndPoint)}");
                                }
                                break;
                            }
                            else
                            {
                                receiveErrorCount++;
                                if (receiveErrorCount >= this._tcpClientInitPara.SynReceiveErrorMaxRepeatCount)
                                {
                                    ZLoger.Error(sex, $"同步接收数据时发生异常,错误码:\"{sex.SocketErrorCode.ToString()}\",超过最大重试次数:\"{this._tcpClientInitPara.SynReceiveErrorMaxRepeatCount}\"，断开连接,RemoteEndPoint:{NetHelper.GetIPPortString(this._linkInfo.RemoteEndPoint)}");
                                    break;
                                }
                                else
                                {
                                    ZLoger.Error(sex, $"同步接收数据时发生异常,错误码:\"{sex.SocketErrorCode.ToString()}\",RemoteEndPoint:{NetHelper.GetIPPortString(this._linkInfo.RemoteEndPoint)}");
                                    totalDataLength = 0;
                                    if (!this.SetReaderPosition(unpackerPara.Reader, 0L))
                                    {
                                        //资源已释放
                                        break;
                                    }
                                    writeOffset = 0;
                                    continue;
                                }
                            }
                        }

                        if (revLen <= 0)
                        {
                            this._continuousReceiveEmptyDataCount++;
                            if (this.CheckContinuousReceiveEmptyDataToLimit())
                            {
                                //连接收到长度为0的包,tcp连接意外断开
                                break;
                            }
                            else
                            {
                                //注:即使是接收到数据长度等于0,也还是触发拆包,有些特殊场景下以发送数据长度为0的包来作边界处理,所以不能忽略长度为0的数据处理逻辑
                            }

                            continue;
                        }
                        else
                        {
                            base.UpdateLastReceiveDataTimestamp();
                            this._continuousReceiveEmptyDataCount = 0;
                            writeOffset += revLen;
                            totalDataLength += revLen;
                        }

                        //分包参数
                        if (!this.SetReaderPosition(unpackerPara.Reader, readOffset))
                        {
                            //资源已释放
                            break;
                        }
                        unpackerPara.Offset = readOffset;
                        unpackerPara.DataLength = totalDataLength;
                        unpackerPara.ReceiveLength = revLen;

                        //分包
                        unpackedDataLength = this._tcpClientInitPara.Unpacker.UnPackge(unpackerPara);
                        if (unpackedDataLength != 0)
                        {
                            readOffset += unpackedDataLength;
                            totalDataLength -= unpackedDataLength;
                        }

                        if (totalDataLength == 0)
                        {
                            //总数据长度为0时,默认从0开始接收
                            writeOffset = 0;
                            readOffset = 0;
                            receiveDataSize = buffer.Length;
                        }
                        else
                        {
                            if (buffer.Length - totalDataLength < receiveDataMinSize)
                            {
                                //当准备用于接收数据的长度小于了单次接收数据大小时,说明最大数据包比当前开辟的接收缓存要大,则扩展接收数据buffer
                                this.ExtendReceiveBuffer(this._tcpClientInitPara.Certificate, CaculateExtendParseBufferLength(buffer.Length));
                                buffer = this._buffer;
                            }

                            receiveDataSize = buffer.Length - writeOffset;
                            if (receiveDataSize < receiveDataMinSize)
                            {
                                //剩余接收数据空间不足,将未解析数据移动到buffer开始位置
                                if (totalDataLength > 0)
                                {
                                    Array.Copy(buffer, readOffset, buffer, 0, totalDataLength);
                                }

                                readOffset = 0;
                                writeOffset = totalDataLength;
                                receiveDataSize = buffer.Length - writeOffset;
                            }
                        }
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        totalDataLength = 0;
                        if (!this.SetReaderPosition(unpackerPara.Reader, 0L))
                        {
                            //资源已释放
                            break;
                        }
                        writeOffset = 0;
                    }
                    catch (ThreadAbortException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        ZLoger.Error(ex, "同步接收数据异常");
                    }
                }
            }
            catch (ThreadAbortException)
            { }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }

            try
            {
                this.SocketDispose();

                //发送连接断开通知
                this.ConnectionCloseNotify();
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

        /// <summary>
        /// 检查连接收到长度为0的数据时否达到上限[达到上限返回true,否则返回false]
        /// </summary>
        /// <returns>达到上限返回true,否则返回false</returns>
        private bool CheckContinuousReceiveEmptyDataToLimit()
        {
            if (this._tcpClientInitPara.MaxReceiveEmpyDataCount <= 0 ||
                this._tcpClientInitPara.MaxReceiveEmpyDataCount > 0 && this._continuousReceiveEmptyDataCount >= this._tcpClientInitPara.MaxReceiveEmpyDataCount)
            {
                //当连续接收到长度为0的数据MaxReceiveEmpyDataCount次,确定对方断开,不再接收数据,由接收数据循环跳出后触发连接断开通知
                return true;
            }
            else
            {
                return false;
            }
        }


        private void RecvEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive:
                    this.ProcessAsyncReceive(e);
                    break;
                case SocketAsyncOperation.Send:
                    //ProcessSend(e);
                    break;
                default:
                    throw new ArgumentException("The last operation completed on the socket was not a receive or send");
            }
        }

        private int _asyncReceiveThreadReceiveCount = 0;
        /// <summary>
        /// tcp客户端开始接受tcp服务器发送的数据
        /// </summary>
        private void StartRecv(SocketAsyncEventArgs args)
        {
            if (this._disposed)
            {
                return;
            }

            this._asyncReceiveThreadReceiveCount++;
            if (this._asyncReceiveThreadReceiveCount > this._tcpClientInitPara.AsyncReceiveStackDepth)
            {
                this._asyncReceiveThreadReceiveCount = 0;
                Task.Factory.StartNew(this.PrimitiveStartRecv, args);
            }
            else
            {
                this.PrimitiveStartRecv(args);
            }
        }

        private void PrimitiveStartRecv(object obj)
        {
            var args = (SocketAsyncEventArgs)obj;
            bool willRaiseEvent = args.AcceptSocket.ReceiveAsync(args);
            if (!willRaiseEvent)
            {
                this.ProcessAsyncReceive(args);
            }
        }



        private int _asyncTotalDataLength = 0;
        private int _asyncReadOffset = 0;
        /// <summary>
        /// 处理接受到的tcp服务器数据
        /// </summary>
        /// <param name="e"></param>
        private void ProcessAsyncReceive(SocketAsyncEventArgs e)
        {
            try
            {
                switch (e.SocketError)
                {
                    case SocketError.Success:
                        try
                        {
                            base.UpdateLastReceiveDataTimestamp();

                            if (e.BytesTransferred <= 0)
                            {
                                this._continuousReceiveEmptyDataCount++;
                                if (this.CheckContinuousReceiveEmptyDataToLimit())
                                {
                                    //连接收到长度为0的包,tcp连接意外断开
                                    this.ProcessAsyncReceiveDisconnect(e);
                                    return;
                                }
                                else
                                {
                                    //注:即使是接收到数据长度等于0,也还是触发拆包,有些特殊场景下以发送数据长度为0的包来作边界处理,所以不能忽略长度为0的数据处理逻辑
                                }
                            }
                            else
                            {
                                this._asyncTotalDataLength += e.BytesTransferred;
                                this._continuousReceiveEmptyDataCount = 0;
                            }

                            NetTcpUnpackerPara unpackerPara = this._unpackerPara;
                            unpackerPara.Offset = this._asyncReadOffset;
                            if (!this.SetReaderPosition(unpackerPara.Reader, this._asyncReadOffset))
                            {
                                //资源已释放
                                this.ProcessAsyncReceiveDisconnect(e);
                                return;
                            }
                            unpackerPara.DataLength = this._asyncTotalDataLength;
                            unpackerPara.ReceiveLength = e.BytesTransferred;

                            int unpackedDataLength = this._tcpClientInitPara.Unpacker.UnPackge(unpackerPara);
                            if (unpackedDataLength > 0)
                            {
                                this._asyncTotalDataLength -= unpackedDataLength;
                                this._asyncReadOffset += unpackedDataLength;
                            }

                            if (e.BytesTransferred > 0)
                            {
                                if (this._asyncTotalDataLength > 0)
                                {
                                    if (e.Buffer.Length - this._asyncTotalDataLength < this._tcpClientInitPara.ReceiveDataSize)
                                    {
                                        //当准备用于接收数据的长度小于了单次接收数据大小时,说明最大数据包比当前开辟的接收缓存要大,则扩展接收数据buffer
                                        this.ExtendReceiveBuffer(this._tcpClientInitPara.Certificate, CaculateExtendParseBufferLength(e.Buffer.Length));
                                    }

                                    //调整下一次接收数据位置
                                    int receiveWriteOffset = e.Offset + e.BytesTransferred;
                                    if (e.Buffer.Length - receiveWriteOffset < this._tcpClientInitPara.ReceiveDataSize)
                                    {
                                        if (this._asyncTotalDataLength > 0)
                                        {
                                            Array.Copy(e.Buffer, this._asyncReadOffset, e.Buffer, 0, this._asyncTotalDataLength);
                                        }
                                        this._asyncReadOffset = 0;
                                        receiveWriteOffset = this._asyncTotalDataLength;
                                    }

                                    e.SetBuffer(this._buffer, receiveWriteOffset, this._buffer.Length - this._asyncTotalDataLength);
                                }
                                else
                                {
                                    this._asyncReadOffset = 0;
                                    e.SetBuffer(this._buffer, 0, this._buffer.Length);
                                }
                            }
                        }
                        catch (ArgumentOutOfRangeException aex)
                        {
                            ZLoger.Error(aex);
                            this._asyncTotalDataLength = 0;
                            this._asyncReadOffset = 0;
                            e.SetBuffer(0, this._tcpClientInitPara.ReceiveDataSize);
                        }
                        catch (ObjectDisposedException)
                        {
                            return;
                        }
                        catch (Exception ex)
                        {
                            ZLoger.Error(ex, $"异步接收数据处理异常,e.Buffer.Length:{e.Buffer.Length},_readOffset:{this._asyncReadOffset},_totalDataLength:{this._asyncTotalDataLength}");
                            return;
                        }

                        this.StartRecv(e);
                        break;
                    case SocketError.TimedOut://设置了接收数据超时时长,接收数据超时
                        this.StartRecv(e);
                        break;
                    case SocketError.ConnectionReset://对方程序关掉(关非连接断开)
                    case SocketError.Shutdown://连接已断开
                    default:
                        this.ProcessAsyncReceiveDisconnect(e);
                        break;
                }
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

        private void ProcessAsyncReceiveDisconnect(SocketAsyncEventArgs e)
        {
            e.Completed -= this.RecvEventArgs_Completed;

            this.SocketDispose();

            //连接断开通知
            this.ConnectionCloseNotify();
        }



        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            try
            {
                if (this._manualDisconnectFlag)
                {
                    return;
                }

                this._manualDisconnectFlag = true;
                if (this._syncRecceiveDataThread != null)
                {
                    this._syncRecceiveDataThread.Stop();
                }

                if (this.Connected)
                {
                    this._client?.Shutdown(SocketShutdown.Both);
                    this._client?.Dispose();
                    this._client = null;
                }
            }
            catch (ObjectDisposedException)
            { }
        }




        private Socket GetSendSocket()
        {
            if (this._disposed)
            {
#if CORE
                ObjectDisposedException.ThrowIf(this._disposed, this);
#else
                throw new ObjectDisposedException(this.ToString());
#endif
            }

            Socket client = this._client;
            if (client == null || !client.Connected)
            {
                if (this._tcpClientInitPara.ConnectType == ConnectTypes.Active)
                {
                    throw new ConnectException($"未连接到\"{NetHelper.GetIPPortString(this._tcpClientInitPara.RemoteEndPoint)}\"");
                }
                else
                {
                    throw new ConnectException($"客户端\"{NetHelper.GetIPPortString(this._linkInfo.RemoteEndPoint)}\"已断开连接");
                }
            }

            return client;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bufferData">要发送的数据对象</param>
        /// <param name="options">发送选项</param>
        unsafe protected override void PrimitiveSend(DataSource bufferData, ISendOptions options)
        {
            if (bufferData == null ||
                bufferData.DataType != DataSourceType.File && bufferData.Length == 0)
            {
                return;
            }

            var tcpSendOptions = (NetTcpSendDataOptions)options;
            switch (bufferData.DataType)
            {
                case DataSourceType.Bytes:
                    if (tcpSendOptions != null)
                    {
                        this.Send(bufferData.Bytes, bufferData.Offset, bufferData.Length, tcpSendOptions.SocketFlags);
                    }
                    else
                    {
                        this.Send(bufferData.Bytes, bufferData.Offset, bufferData.Length);
                    }
                    break;
                case DataSourceType.Stream:
                    if (tcpSendOptions != null)
                    {
                        this.Send(bufferData.Stream, bufferData.LongOffset, bufferData.LongLength, tcpSendOptions.SocketFlags);
                    }
                    else
                    {
                        this.Send(bufferData.Stream, bufferData.LongOffset, bufferData.LongLength);
                    }
                    break;
                case DataSourceType.File:
                    if (bufferData.OffsetAndLengthHasValid)
                    {
                        using (FileStream fs = File.OpenRead(bufferData.FilePath))
                        {
                            bufferData.UpdateFileBufferLength(fs.Length);
                            if (tcpSendOptions != null)
                            {
                                this.Send(fs, bufferData.LongOffset, bufferData.LongLength, tcpSendOptions.SocketFlags);
                            }
                            else
                            {
                                this.Send(fs, bufferData.LongOffset, bufferData.LongLength);
                            }
                        }
                    }
                    else
                    {
                        this.Send(bufferData.FilePath);
                    }
                    break;
#if CORE
                case DataSourceType.Memory:
                    this.Send(bufferData.MemoryBuffer.Span);
                    break;
#endif
                case DataSourceType.BinaryReader:
                    if (tcpSendOptions != null)
                    {
                        this.Send(bufferData.Reader.BaseStream, bufferData.LongOffset, bufferData.LongLength, tcpSendOptions.SocketFlags);
                    }
                    else
                    {
                        this.Send(bufferData.Reader.BaseStream, bufferData.LongOffset, bufferData.LongLength);
                    }
                    break;
                case DataSourceType.DataPtr:
                    using (var ums = new UnmanagedMemoryStream(bufferData.DataPtr, bufferData.LongLength))
                    {
                        if (tcpSendOptions != null)
                        {
                            this.Send(ums, 0, bufferData.LongLength, tcpSendOptions.SocketFlags);
                        }
                        else
                        {
                            this.Send(ums, 0, bufferData.LongLength);
                        }
                    }
                    break;
                default:
                    throw new NotImplementedException($"{nameof(NetTcpClient)}发送数据,未实现的缓存数据类型{bufferData.DataType.ToString()}");
            }
        }




        #region 同步发送
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer">数据</param>
        /// <param name="offset">数据中偏移位置,小于等于0表示从0开始</param>
        /// <param name="length">要发送的数据长度,小于等于0表示发送到数据结尾</param>
        /// <param name="socketFlags">SocketFlags</param>
        public void Send(byte[] buffer, int offset = 0, int length = -1, SocketFlags socketFlags = SocketFlags.None)
        {
#if CORE
            ArgumentNullException.ThrowIfNull(buffer);
#else
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
#endif

            if (offset < 0)
            {
                offset = 0;
            }
            else if (offset >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            //ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(offset, buffer.Length, nameof(offset));


            if (length < 0)
            {
                length = buffer.Length - offset;
            }
            else if (offset + length > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            lock (this._sendDataLock)
            {
                Socket client = this.GetSendSocket();
                int sendedLength;
                while (length > 0)
                {
                    try
                    {
                        sendedLength = client.Send(buffer, offset, length, socketFlags);
                        offset += sendedLength;
                        length -= sendedLength;
                    }
                    catch (ObjectDisposedException)
                    {
                        throw;
                    }
                    catch (SocketException sex)
                    {
                        if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                        {
                            this.SocketDispose();
                            this.ConnectionCloseNotify();
                        }

                        throw;
                    }
                }
            }
            base.UpdateLastSendDataTimestamp();
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="offset">数据中偏移位置,小于等于0表示从0开始</param>
        /// <param name="length">要发送的数据长度,小于等于0表示发送到数据结尾</param>
        /// <param name="socketFlags">SocketFlags</param>
        public void Send(Stream stream, long offset = 0, long length = -1, SocketFlags socketFlags = SocketFlags.None)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (offset < 0)
            {
                offset = 0;
            }
            else if (offset >= stream.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (length < 0)
            {
                length = stream.Length - offset;
            }
            else if (offset + length > stream.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            try
            {
                byte[] buffer;
                if (length >= NetHelper.TCP_PACKAGE)
                {
                    buffer = new byte[NetHelper.TCP_PACKAGE];
                }
                else
                {
                    buffer = new byte[length];
                }

                long mod;
                int sendLength = buffer.Length;
                long endPosition = offset + length;
                stream.Seek(offset, SeekOrigin.Begin);

                lock (this._sendDataLock)
                {
                    Socket client = this.GetSendSocket();
                    int sendedLength;
                    while (stream.Position < endPosition)
                    {
                        mod = endPosition - stream.Position;
                        if (mod < buffer.Length)
                        {
                            sendLength = (int)mod;
                        }
                        stream.Read(buffer, 0, sendLength);

                        while (length > 0)
                        {
                            try
                            {
                                sendedLength = client.Send(buffer, 0, sendLength, socketFlags);
                                offset += sendedLength;
                                length -= sendedLength;
                            }
                            catch (ObjectDisposedException)
                            {
                                throw;
                            }
                            catch (SocketException sex)
                            {
                                if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                                {
                                    this.SocketDispose();
                                    this.ConnectionCloseNotify();
                                }

                                throw;
                            }
                        }
                    }
                }
                base.UpdateLastSendDataTimestamp();
            }
            catch (ObjectDisposedException)
            {
                return;
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public void Send(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("要发送的文件不存在", filePath);
            }

            try
            {
                lock (this._sendDataLock)
                {
                    Socket client = this.GetSendSocket();
                    client.SendFile(filePath);
                }
                base.UpdateLastSendDataTimestamp();
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (SocketException sex)
            {
                if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                {
                    this.SocketDispose();
                    this.ConnectionCloseNotify();
                }

                throw;
            }
        }

#if CORE
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer">数据</param>
        public void Send(Span<byte> buffer)
        {
            try
            {
                if (buffer.Length <= 0)
                {
                    throw new ArgumentNullException(nameof(buffer), "不支持发送长度为0的数据");
                }

                lock (this._sendDataLock)
                {
                    Socket client = this.GetSendSocket();
                    client.Send(buffer);
                }
                base.UpdateLastSendDataTimestamp();
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (SocketException sex)
            {
                if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                {
                    this.SocketDispose();
                    this.ConnectionCloseNotify();
                }

                throw;
            }
        }
#endif
        #endregion



        #region 异步发送

        private SocketAsyncEventArgs _sendSocketAsyncEventArgs = null;
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer">数据</param>
        /// <param name="offset">数据中偏移位置,小于等于0表示从0开始</param>
        /// <param name="length">要发送的数据大小,小于等于0表示发送到数据结尾</param>
        public void SendAsync(byte[] buffer, int offset = 0, int length = -1)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (offset < 0)
            {
                offset = 0;
            }
            else if (offset >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (length < 0)
            {
                length = buffer.Length - offset;
            }

            if (offset + length > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            try
            {
                Socket client = this.GetSendSocket();
                if (this._sendSocketAsyncEventArgs == null)
                {
                    this._sendSocketAsyncEventArgs = new SocketAsyncEventArgs();
                    this._sendSocketAsyncEventArgs.Completed += this.SendSocketAsyncEventArgs_Completed;
                }
                this._sendSocketAsyncEventArgs.SetBuffer(buffer, offset, length);
                if (!client.SendAsync(this._sendSocketAsyncEventArgs))
                {
                    this.ProcessSendCompleted(this._sendSocketAsyncEventArgs);
                }
            }
            catch (ObjectDisposedException)
            {
                return;
            }
        }

        private void SendSocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            this.ProcessSendCompleted(e);
        }

        private void ProcessSendCompleted(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                base.UpdateLastSendDataTimestamp();
            }
            else
            {
                ZLoger.Error($"发送数据到\"{NetHelper.GetIPPortString(this._linkInfo.RemoteEndPoint)}\"失败");

                if (NetHelper.SocketErrorIsDisconnect(e.SocketError))
                {
                    this.SocketDispose();
                    this.ConnectionCloseNotify();
                }
            }
        }


#if CORE
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public async void SendFileAsync(string filePath)
        {
            try
            {
                Socket client = this.GetSendSocket();
                await client.SendFileAsync(filePath, this._cts.Token);
                base.UpdateLastSendDataTimestamp();
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (SocketException sex)
            {
                if (NetHelper.SocketErrorIsDisconnect(sex.SocketErrorCode))
                {
                    this.SocketDispose();
                    this.ConnectionCloseNotify();
                }

                throw;
            }
        }
#endif

        #endregion



        /// <summary>
        /// Dispose
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (this._enableSendHeartData)
                {
                    ClientHeartManager.Instance.Remove(this);
                }

                if (this._syncRecceiveDataThread != null)
                {
                    this._syncRecceiveDataThread.Stop();
                    this._syncRecceiveDataThread.Dispose();
                }

                this.SocketDispose();
                this._reader.Dispose();
                this._cts.Cancel();
                this._cts.Dispose();
                if (this._sendSocketAsyncEventArgs != null)
                {
                    this._sendSocketAsyncEventArgs.Completed -= this.SendSocketAsyncEventArgs_Completed;
                    this._sendSocketAsyncEventArgs.Dispose();
                }
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex, "资源释放异常");
            }
        }
    }
}
